package com.yxx.strategy.loginStrategyImpl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yxx.entity.User;
import com.yxx.entity.UserRole;
import com.yxx.entityModel.dto.SocialTokenDTO;
import com.yxx.entityModel.dto.SocialUserInfoDTO;
import com.yxx.entityModel.vo.request.CodeRequest;
import com.yxx.enums.RoleEnum;
import com.yxx.mapper.UserMapper;
import com.yxx.mapper.UserRoleMapper;
import com.yxx.strategy.LoginStrategy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 抽象登录模板
 * @author yuxiangxun
 * @date 2025/2/5
 * @apiNote
 */
@Service
public abstract class AbstractLoginStrategyImpl implements LoginStrategy {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserRoleMapper userRoleMapper;

    /**
     * 第三方登录
     * @param data 第三方登录
     * @return Token
     */
    @Override
    public String login(CodeRequest data) {
        // 获取 第三方Token  根据前端请求过来的code
        SocialTokenDTO socialTokenDTO = getSocialTokenDTO(data);
        // 获取 第三方用户信息
        SocialUserInfoDTO socialUserInfoDTO = getSocialUserInfo(socialTokenDTO);
        // 判断是否已注册 根据获取用户信息中的姓名以及第三方Token中的登录类型进行判断
        User existUser = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .select(User::getId)
                .eq(User::getUsername, socialUserInfoDTO.getNickname())
                .eq(User::getLoginType, socialTokenDTO.getLoginType()));
        User user;
        // 如果查询出来为null，证明不存在，那么进行注册（新增用户信息）操作
        if(Objects.isNull(existUser)){
            user = saveLoginUser(socialTokenDTO, socialUserInfoDTO);
        } else {
            user = existUser;
        }
        // 校验指定账号是否已被封禁，如果被封禁则抛出异常 `DisableServiceException`
        StpUtil.checkDisable(user.getId());
        // 通过校验后，再进行登录
        StpUtil.login(user.getId());
        return StpUtil.getTokenValue();
    }

    /**
     * 新增用户账号
     * @param socialTokenDTO 第三方Token
     * @param socialUserInfoDTO 登录用户身份权限
     * @return
     */
    public User saveLoginUser(SocialTokenDTO socialTokenDTO, SocialUserInfoDTO socialUserInfoDTO){
        User newUser = User.builder()
                .avatar(socialUserInfoDTO.getAvatar())
                .nickname(socialUserInfoDTO.getNickname())
                .username(socialUserInfoDTO.getId())
                .password(socialTokenDTO.getAccessToken())
                .build();
        userMapper.insert(newUser);
        UserRole userRole = UserRole.builder()
                .userId(newUser.getId())
                .roleId(RoleEnum.USER.getRoleId())
                .build();
        userRoleMapper.insert(userRole);
        return newUser;
    }


    /**
     * 获取 第三方Token
     * 模板方法
     * @param data data
     * @return 第三方Token
     */
    public abstract SocialTokenDTO getSocialTokenDTO(CodeRequest data);

    /**
     * 获取 第三方用户信息
     * @param socialTokenDTO 第三方token
     * @return {@link SocialUserInfoDTO} 第三方用户信息
     */
    public abstract SocialUserInfoDTO getSocialUserInfo(SocialTokenDTO socialTokenDTO);


}
